43. Get name from template base class

class CompanyA{
public:
// ...
void sendCleartext(const std::string& msg);
void sendEncrypted(const std::string& msg);
// ...
};
class CompanyB{
public:
// ...
void sendCleartext(const std::string& msg);
void sendEncrypted(const std::string& msg);
};
// ...
class MsgInfo{/*...*/};
// Company
template <typename Company>
class MsgSender{
public:
// ...
void sendClear(const MsgInfo& info){
std::string msg;
Company c;
c.sendCleartext(msg);
}
void sendSecret(const MsgInfo& info){/*...*/}
};
//
template <typename Company>
class LogginMsgSender: pubic MsgSender<Company>{
public:
// ...
void sendClearMsg(const MsgInfo& info){
//
sendClear(info); // compile error
//
}
};
위에서 MsgSender 클래스는 Template 인자를 컴파일 타임에 미리 알고 있는 경우,
문제 없이 동작시킬 수 있다.

하지만, LoggingMsgSender class는 기본 클래스에 정의되어 있는 sendClear 함수를 찾지 못한다.

LogginMsgSender는 MsgSender<Company>에서 파생되었지만,
템플릿 매개변수 Company가 무엇이 될지는 LogginMsgSender의 인스턴스가 생성되기 전까지 알 수가 없다.
(MsgSender<Company>를 알 수 없기 때문에 sendClass 존재 유무도 알 수가 없음)
class CompanyZ{
public:
// ...
void sendEncrypted(const std::string& msg);
// ...
};
// 릿
template <>
class MsgSender<CompanyZ>{
public:
// ...
void sendSecret(const MsgInfo& info);
};
완전 템플릿 특수화(Total Template Specialization)
template <typename Company>
class LoggingMsgSender: public MsgSender<Company>{
public:
// ...
void sendClearMsg(const MsgInfo& info){
// ...
sendClear(info); // Company CompanyZ ,
// ...
}
}
위와 같이 기본 클래스 템플릿은 언제든지 특수화될 수 있으며, 특수화 버전에서 제공하는 인터페이스가
일반형 템플릿과 항상 같지 않기 때문에 C++ 컴파일러는 템플릿으로 만들어진 기본 클래스에서 상속된 이름을
찾지 않는다.
템플릿 기본 클래스에서 함수를 상속받아 사용하기 위한 방법
1. this-> 사용
template <typename Company>
class LoggingMsgSender: public MsgSender<Company>{
public:
// ...
void sendClearMsg(const MsgInfo& info){
// ...
this->sendClear(info); // .sendClear()
// ...
}
// ...
};
2. using 사용
template <typename Company>
class LoggingMsgSender: public MsgSender<Company>{
public:
// sendClear
using MsgSender<Company>::sendClear;
// ...
void sendClearMsg(const MsgInfo& info){
// ...
sendClear(info); // sendClear
// ...
}
// ...
};
3. 호출할 함수가 기본 클래스의 함수라는 점을 명시적으로 지정
단, 위와 같이 호출하는 경우 호출하는 함수가 가상함수라면 가상함수 바인딩이 무시될 수 있다.
template <typename Company>
class LoggingMsgSender: public MsgSender<Company>{
public:
// ...
void sendClearMsg(const MsgInfo& info){
// ...
MsgSender<Company>::sendClear(info); // sendClear
// ...
}
// ...
};